package com.xxg.renrenorder.service;

import com.xxg.renrencommon.domain.filedenum.orderenum.AfterSalesOrderStatusEnum;
import com.xxg.renrencommon.domain.filedenum.orderenum.OrderStatusEnum;
import com.xxg.renrencommon.domain.result.BaseResult;
import com.xxg.renrencommon.domain.result.PageInfoResult;
import com.xxg.renrencommon.exception.ErrorMessage;
import com.xxg.renrencommon.exception.OrderManagerException;
import com.xxg.renrencommon.exception.exceptionenum.OrderExceptionCodeCodeEnum;
import com.xxg.renrenorder.dao.AfterSalesOrderInfoDao;
import com.xxg.renrenorder.dao.OrderMasterInfoDao;
import com.xxg.renrenorder.dao.bean.AfterSalesOrderInfo;
import com.xxg.renrenorder.dao.bean.AfterSalesStep;
import com.xxg.renrenorder.dao.bean.OrderMasterInfo;
import com.xxg.renrenorder.domain.query.AfterSalesOrderListQuery;
import com.xxg.renrenorder.domain.query.VerifyOrderQuery;
import com.xxg.renrenorder.strategy.AbstractAfterSalesStrategy;
import com.xxg.renrenorder.strategy.AfterSalesStrategy;
import com.xxg.renrenorder.strategy.AfterSalesStrategyContext;
import com.xxg.renrenorder.util.DateTimeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

/**
 * 售后订单接口实现
 *
 * @author xxg
 * @date 2021/4/16
 */
@Service
@Slf4j
public class AfterSalesOrderServiceImpl implements AfterSalesOrderService {
    private final OrderMasterInfoDao orderMasterInfoDao;
    private final AfterSalesOrderInfoDao afterSalesOrderInfoDao;
    private final HashMap<Integer, Set<Integer>> statusMap;
    private final HashMap<Integer, Integer> typeMap;

    public AfterSalesOrderServiceImpl(OrderMasterInfoDao orderMasterInfoDao, AfterSalesOrderInfoDao afterSalesOrderInfoDao) {
        this.orderMasterInfoDao = orderMasterInfoDao;
        this.afterSalesOrderInfoDao = afterSalesOrderInfoDao;
        statusMap = initAfterSalesStatus();
        typeMap = initAfterSalesType();
    }

    /**
     * 初始化售后订单状态流转字典
     *
     * @return 状态流转
     */
    private HashMap<Integer, Set<Integer>> initAfterSalesStatus() {
        HashMap<Integer, Set<Integer>> statusMap = new HashMap<>();
        // 待审核
        Integer[] status1 = {1, 2, 10, 13, 16, 18, 4, 9};
        Set<Integer> nextStatus = new HashSet<>(Arrays.asList(status1));
        statusMap.put(AfterSalesOrderStatusEnum.UN_VERIFY.getValue(), nextStatus);
        // 待退货 (该状态下可能需要审核拒绝)
        Integer[] status3 = {20, 4};
        nextStatus = new HashSet<>(Arrays.asList(status3));
        statusMap.put(AfterSalesOrderStatusEnum.UN_RETURN_EXPRESS.getValue(), nextStatus);
        // 维修申请待退货(该状态下可能需要审核拒绝)
        Integer[] status4 = {11, 4};
        nextStatus = new HashSet<>(Arrays.asList(status4));
        statusMap.put(AfterSalesOrderStatusEnum.REPAIR_WAIT_RETURN.getValue(), nextStatus);
        // 已收到货维修中
        Integer[] status5 = {12};
        nextStatus = new HashSet<>(Arrays.asList(status5));
        statusMap.put(AfterSalesOrderStatusEnum.REPAIRING.getValue(), nextStatus);
        // 换货申请待退货(该状态下可能需要审核拒绝)
        Integer[] status6 = {14, 4};
        nextStatus = new HashSet<>(Arrays.asList(status6));
        statusMap.put(AfterSalesOrderStatusEnum.CHANGE_WAIT_RETURN.getValue(), nextStatus);
        // 已收到货换货中
        Integer[] status7 = {15};
        nextStatus = new HashSet<>(Arrays.asList(status7));
        statusMap.put(AfterSalesOrderStatusEnum.CHANGING.getValue(), nextStatus);
        // 补寄商品中
        Integer[] status8 = {17};
        nextStatus = new HashSet<>(Arrays.asList(status8));
        statusMap.put(AfterSalesOrderStatusEnum.REPLENISHMENT.getValue(), nextStatus);
        // 补寄零件中
        Integer[] status9 = {19};
        nextStatus = new HashSet<>(Arrays.asList(status9));
        statusMap.put(AfterSalesOrderStatusEnum.REPLENISHMENT_PART.getValue(), nextStatus);
        return statusMap;
    }

    /**
     * 特定售后类型下审核通过对应的状态
     *
     * @return 类型审核通过后的状态
     */
    private HashMap<Integer, Integer> initAfterSalesType() {
        HashMap<Integer, Integer> hashMap = new HashMap<>();
        Integer[] type = {1, 3, 4, 5, 6, 7};
        Integer[] status = {2, 1, 10, 13, 16, 18};
        for (int i = 0; i < 6; i++) {
            hashMap.put(type[i], status[i]);
        }
        return hashMap;
    }

    @Override
    public BaseResult<Void> applyAfterSalesOrder(AfterSalesOrderInfo afterSalesOrderInfo) {
        // 查询订单详情
        OrderMasterInfo orderMasterInfo = orderMasterInfoDao.getOrderByOrderId(afterSalesOrderInfo.getOrderId());
        if (orderMasterInfo == null) {
            return new BaseResult<>(OrderExceptionCodeCodeEnum.APPLY_AFTER_SALES_ERROR);
        }
        afterSalesOrderInfo.setReturnPay(new BigDecimal("0"));
        boolean returnProduct;
        AfterSalesStrategyContext strategyContext = new AfterSalesStrategyContext(afterSalesOrderInfoDao, afterSalesOrderInfo.getAfterSalesType());
        try {
            AfterSalesStrategy afterSalesStrategy = strategyContext.handlerAfterSalesOrderInfo(afterSalesOrderInfo, orderMasterInfo, true);
            returnProduct = afterSalesStrategy.getReturnProduct();
        } catch (OrderManagerException e) {
            log.error(e.getMessage(), e);
            return new BaseResult<>(e);
        }
        // 更新原订单中商品的售后状态
        orderMasterInfoDao.updateProductStatus(afterSalesOrderInfo.getOrderId(),
                afterSalesOrderInfo.getProductInfo().getSkuId(), AfterSalesOrderStatusEnum.UN_VERIFY.getValue());
        afterSalesOrderInfoDao.applyAfterSalesOrder(afterSalesOrderInfo);
        // 如果是退款、退货退款则需要修改原订单中退货商品数量
        if (returnProduct && afterSalesOrderInfo.getNumber() != null) {
            orderMasterInfoDao.updateProductReturnNumber(afterSalesOrderInfo.getOrderId(),
                    afterSalesOrderInfo.getProductInfo().getSkuId(), afterSalesOrderInfo.getNumber(), null);
        }
        return new BaseResult<>();
    }

    @Override
    public BaseResult<Void> cancelAfterSalesOrder(String id, String userId) {
        // 只有待审核的售后订单才能撤销
        AfterSalesOrderInfo salesOrderInfo = afterSalesOrderInfoDao.getOrderByOrderId(id);
        if (salesOrderInfo == null) {
            return new BaseResult<>(OrderExceptionCodeCodeEnum.AFTER_SALES_NOT_EXISTS);
        } else if (salesOrderInfo.getStatus() == AfterSalesOrderStatusEnum.UN_VERIFY.getValue()
                || salesOrderInfo.getStatus() == AfterSalesOrderStatusEnum.UN_RETURN_EXPRESS.getValue()
                || salesOrderInfo.getStatus() == AfterSalesOrderStatusEnum.REPAIR_WAIT_RETURN.getValue()
                || salesOrderInfo.getStatus() == AfterSalesOrderStatusEnum.CHANGE_WAIT_RETURN.getValue()) {
            salesOrderInfo.setStatus(AfterSalesOrderStatusEnum.CANCEL.getValue());
            AbstractAfterSalesStrategy.setStep(new Date(), salesOrderInfo, "买家已撤销申请", 0);
            afterSalesOrderInfoDao.saveAfterSalesOrder(salesOrderInfo);
            orderMasterInfoDao.updateProductStatus(salesOrderInfo.getOrderId(), salesOrderInfo.getProductInfo().getSkuId(), AfterSalesOrderStatusEnum.CANCEL.getValue());
            return new BaseResult<>();
        } else {
            return new BaseResult<>(OrderExceptionCodeCodeEnum.ONLY_UN_VERIFY_CAN_CANCEL);
        }
    }

    @Override
    public BaseResult<Void> editAfterSalesOrder(AfterSalesOrderInfo afterSalesOrderInfo) {
        // 只有审核不通过的售后订单才允许修改
        AfterSalesOrderInfo salesOrderInfo = afterSalesOrderInfoDao.getOrderByOrderId(afterSalesOrderInfo.getId());
        if (salesOrderInfo == null) {
            return new BaseResult<>(OrderExceptionCodeCodeEnum.AFTER_SALES_NOT_EXISTS);
        }
        if (salesOrderInfo.getStatus() != AfterSalesOrderStatusEnum.REJECTED.getValue()) {
            return new BaseResult<>(OrderExceptionCodeCodeEnum.ONLY_REJECTED_CAN_EDIT);
        }
        if (!afterSalesOrderInfo.getUserId().equals(salesOrderInfo.getUserId())) {
            return new BaseResult<>(OrderExceptionCodeCodeEnum.AFTER_SALES_USER_ID_ERROR);
        }
        // 查询订单详情
        OrderMasterInfo orderMasterInfo = orderMasterInfoDao.getOrderByOrderId(afterSalesOrderInfo.getOrderId());
        if (orderMasterInfo == null) {
            return new BaseResult<>(OrderExceptionCodeCodeEnum.ORDER_NOT_EXISTS);
        }
        afterSalesOrderInfo.setReturnPay(new BigDecimal("0"));
        boolean returnProduct;
        try {
            AfterSalesStrategyContext strategyContext = new AfterSalesStrategyContext(afterSalesOrderInfoDao, afterSalesOrderInfo.getAfterSalesType());
            AfterSalesStrategy afterSalesStrategy = strategyContext.handlerAfterSalesOrderInfo(afterSalesOrderInfo, orderMasterInfo, true);
            returnProduct = afterSalesStrategy.getReturnProduct();
        } catch (OrderManagerException e) {
            return new BaseResult<>(OrderExceptionCodeCodeEnum.APPLY_AFTER_SALES_ERROR, e.getMessage(), null);
        }
        afterSalesOrderInfoDao.saveAfterSalesOrder(afterSalesOrderInfo);
        // 如果时退款、退货退款则需要修改原订单中退货商品数量
        if (returnProduct && afterSalesOrderInfo.getNumber() != null) {
            orderMasterInfoDao.updateProductReturnNumber(afterSalesOrderInfo.getOrderId(),
                    afterSalesOrderInfo.getProductInfo().getSkuId(), afterSalesOrderInfo.getNumber(), null);
        }
        return new BaseResult<>();
    }

    @Override
    public BaseResult<List<AfterSalesOrderInfo>> getAfterOrderByOrderId(String id) {
        List<AfterSalesOrderInfo> afterSalesOrderInfos = afterSalesOrderInfoDao.getRelatedOrdersByOrderId(id);
        return new BaseResult<>(afterSalesOrderInfos);
    }

    @Override
    public BaseResult<Void> verifyAfterSalesOrder(VerifyOrderQuery verifyOrderQuery) {
        AfterSalesOrderInfo order = afterSalesOrderInfoDao.getOrderByOrderId(verifyOrderQuery.getId());
        if (order != null) {
            Integer currentStatus = order.getStatus();
            if (statusMap.containsKey(currentStatus)) {
                Set<Integer> nextStatus = statusMap.get(currentStatus);
                // 流转的状态是否合法
                if (nextStatus.contains(verifyOrderQuery.getStatus())) {
                    // 对待审核的状态审核通过的流转进行判断
                    if (currentStatus.equals(AfterSalesOrderStatusEnum.UN_VERIFY.getValue())
                            && verifyOrderQuery.getStatus() != AfterSalesOrderStatusEnum.REJECTED.getValue()
                            && verifyOrderQuery.getStatus() != AfterSalesOrderStatusEnum.REJECTED_FOREVER.getValue()) {
                        if (!verifyOrderQuery.getStatus().equals(typeMap.get(order.getAfterSalesType()))) {
                            return new BaseResult<>(OrderExceptionCodeCodeEnum.VERIFY_AFTER_ORDER_ERROR, ErrorMessage.STATUS_ERROR, null);
                        }
                    }
                    if (verifyOrderQuery.getStatus() == 20 || verifyOrderQuery.getStatus() == 11 | verifyOrderQuery.getStatus() == 14) {
                        // 已收到货的时候需要检测用户是否已经填写退货物流信息
                        if (order.getExpressInfo() == null) {
                            return new BaseResult<>(OrderExceptionCodeCodeEnum.VERIFY_AFTER_ORDER_ERROR, ErrorMessage.EXPRESS_CANNOT_NULL, null);
                        }
                    }
                    // 是否属于退款(退款中、已收到货退款中)
                    if (verifyOrderQuery.getStatus() == 2 || verifyOrderQuery.getStatus() == 20) {
                        // 协商退款
                        if (order.getAfterSalesType() == 1 && order.getReasonType() == 6) {
                            order.setRefundReason("协商退款");
                            order.setRealReturnPay(order.getApplyReturnPay());
                        } else {
                            if (verifyOrderQuery.getVerifyType() == null) {
                                return new BaseResult<>(OrderExceptionCodeCodeEnum.VERIFY_AFTER_ORDER_ERROR, ErrorMessage.VERIFY_TYPE_CANNOT_NULL, null);
                            }
                            if (verifyOrderQuery.getLessQuantity() == null) {
                                return new BaseResult<>(OrderExceptionCodeCodeEnum.VERIFY_AFTER_ORDER_ERROR, ErrorMessage.LESS_QUANTITY_CANNOT_NULL, null);
                            }
                        }
                    } else if (verifyOrderQuery.getStatus() == 12 || verifyOrderQuery.getStatus() == 15
                            || verifyOrderQuery.getStatus() == 17 || verifyOrderQuery.getStatus() == 19) {
                        // 维修完成、换货完成、补寄完成、补寄零件完成已寄回需要判断寄回的物流信息
                        if (verifyOrderQuery.getBackExpressInfo() == null || verifyOrderQuery.getBackExpressInfo().size() == 0) {
                            return new BaseResult<>(OrderExceptionCodeCodeEnum.VERIFY_AFTER_ORDER_ERROR, ErrorMessage.BACK_EXPRESS_CANNOT_NULL, null);
                        }
                        order.setBackExpressInfo(verifyOrderQuery.getBackExpressInfo());
                    }
                    // 更新原订单中的售后状态
                    orderMasterInfoDao.updateProductStatus(order.getOrderId(), order.getProductInfo().getSkuId(), verifyOrderQuery.getStatus());
                    // 更新售后状态
                    setStep(new Date(), order, verifyOrderQuery, 1);
                    afterSalesOrderInfoDao.verifyAfterSalesOrder(verifyOrderQuery, order);
                } else {
                    return new BaseResult<>(OrderExceptionCodeCodeEnum.VERIFY_AFTER_ORDER_ERROR, ErrorMessage.STATUS_ERROR, null);
                }
            } else {
                return new BaseResult<>(OrderExceptionCodeCodeEnum.VERIFY_AFTER_ORDER_ERROR, ErrorMessage.STATUS_ERROR, null);
            }
        }
        return new BaseResult<>();
    }

    @Override
    public BaseResult<List<AfterSalesOrderInfo>> getAfterSalesOrders(String userId, Integer pageNo, Integer pageSize) {
        List<AfterSalesOrderInfo> list = afterSalesOrderInfoDao.getAfterSalesOrdersByUserId(userId,
                pageNo - 1, pageSize);
        return new BaseResult<>(list);
    }

    @Override
    public BaseResult<AfterSalesOrderInfo> getAfterSalesOrderById(String id) {
        AfterSalesOrderInfo afterSalesOrderInfo = afterSalesOrderInfoDao.getOrderByOrderId(id);
        return new BaseResult<>(afterSalesOrderInfo);
    }

    @Override
    public BaseResult<Void> removeAfterSalesOrderById(String id, String userId) {
        afterSalesOrderInfoDao.removeAfterSalesOrderById(id, Integer.parseInt(userId));
        return new BaseResult<>();
    }

    @Override
    public BaseResult<PageInfoResult<AfterSalesOrderInfo>> getAllAfterSalesOrdersByStatus(AfterSalesOrderListQuery afterSalesOrderListQuery) {
        String startDate = afterSalesOrderListQuery.getStartDate();
        String endDate = afterSalesOrderListQuery.getEndDate();
        List<Integer> orderStatus = afterSalesOrderListQuery.getOrderStatus();
        Integer pageNo = afterSalesOrderListQuery.getPageNo();
        Integer pageSize = afterSalesOrderListQuery.getPageSize();
        Boolean hasClickReFund = afterSalesOrderListQuery.getHasClickReFund();
        String spuName = afterSalesOrderListQuery.getSpuName();
        Date[] dates;
        try {
            dates = DateTimeUtil.convertDate(startDate, endDate);
        } catch (OrderManagerException e) {
            return new BaseResult<>(OrderExceptionCodeCodeEnum.INVALID_PARAMETER, e.getMessage(), null);
        }
        List<AfterSalesOrderInfo> list = afterSalesOrderInfoDao.getAllAfterSalesOrdersByStatus(orderStatus,
                pageNo - 1, pageSize, dates, hasClickReFund, spuName);
        long count = afterSalesOrderInfoDao.countAllAfterSalesOrdersByStatus(orderStatus, dates, hasClickReFund, spuName);
        PageInfoResult<AfterSalesOrderInfo> pageInfoResult = new PageInfoResult<>(count, list);
        return new BaseResult<>(pageInfoResult);
    }

    /**
     * 插入售后进度
     *
     * @param now                 当前时间
     * @param afterSalesOrderInfo 售后订单
     * @param verifyOrderQuery    售后审核信息
     * @param role                角色
     */
    private void setStep(Date now, AfterSalesOrderInfo afterSalesOrderInfo, VerifyOrderQuery verifyOrderQuery, Integer role) {
        AfterSalesOrderStatusEnum enumConstant = AfterSalesOrderStatusEnum.class.getEnumConstants()[verifyOrderQuery.getStatus()];
        String description = "平台：" + enumConstant.getName();
        if (enumConstant.getValue() == 2 || enumConstant.getValue() == 20) {
            description += "；原因类型：" + (verifyOrderQuery.getVerifyType() ? "个人原因" : "平台原因")
                    + "；是否缺货：" + (verifyOrderQuery.getLessQuantity() ? "是" : "否") + "；其他说明："
                    + ((verifyOrderQuery.getVerifyRemark() == null
                    || verifyOrderQuery.getVerifyRemark().trim().length() == 0) ? "无" : verifyOrderQuery.getVerifyRemark().trim());
        } else if (enumConstant.getValue() == 4 || enumConstant.getValue() == 9) {
            description += "；审核说明：" + verifyOrderQuery.getResponse();
        }
        AfterSalesStep afterSalesStep = new AfterSalesStep();
        afterSalesStep.setCreateTime(now);
        afterSalesStep.setDescription(description);
        afterSalesStep.setRole(role);
        if (afterSalesOrderInfo.getAfterSalesSteps() == null) {
            afterSalesOrderInfo.setAfterSalesSteps(Collections.singletonList(afterSalesStep));
        } else {
            afterSalesOrderInfo.getAfterSalesSteps().add(afterSalesStep);
        }
    }
}
